﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using OpenQuarters.WebQuarters.Core;
using OpenQuarters.WebQuarters.Utils;
using System.Xml.Serialization;
using System.IO;

namespace OpenQuarters.WebQuarters.Modules.MailingList
{
    public class MailingListModule : Module
    {
        [Serializable]
        public struct MailingListOptions
        {
            public string ToAddress;
            public string FromAddress;
            public string Role;
            public string ListName;
        }

        public static Dictionary<string, string> AvailableForms
        {
            get
            {
                Dictionary<string, string> d = new Dictionary<string, string>();
                d.Add("OpenQuarters.WebQuarters.Modules.MailingList,Resources.Default.tpl", "[Default]");

                foreach (string path in System.IO.Directory.GetFiles(Oracle.Request.MapPath("~/Forms/"), "*.tpl"))
                {
                    d.Add(System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetFileName(path));
                }

                return d;
            }
        }

        public static Dictionary<string, string> Roles
        {
            get
            {
                Dictionary<string, string> d = new Dictionary<string, string>();

                foreach (Role role in Role.Table.ToList())
                {
                    d.Add(role.RoleId, role.Name);
                }

                return d;
            }
        }

        private bool use_JavaScript = true;

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.CheckBox)]
        public bool Use_JavaScript
        {
            get { return use_JavaScript; }
            set { use_JavaScript = value; }
        }

        private string introduction_Message = "Please use the form below to get in touch.";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string Introduction_Message
        {
            get { return introduction_Message; }
            set { introduction_Message = value; }
        }

        private string success_Message = "Thank you for subscribing to our mailing list";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string Success_Message
        {
            get { return success_Message; }
            set { success_Message = value; }
        }

        private string add_To_Role = Role.UserRoleId;

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.DropDown, OptionSource = "OpenQuarters.WebQuarters.Modules.MailingList.MailingListModule.Roles")]
        public string Add_To_Role
        {
            get { return add_To_Role; }
            set { add_To_Role = value; }
        }

        private string form = "OpenQuarters.WebQuarters.Modules.MailingList,Resources.Default.tpl";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.DropDown, OptionSource = "OpenQuarters.WebQuarters.Modules.MailingList.MailingListModule.AvailableForms")]
        public string Form
        {
            get { return form; }
            set { form = value; }
        }

        private string to_Address = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string To_Address
        {
            get { return to_Address; }
            set { to_Address = value; }
        }

        private string from_Address = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string From_Address
        {
            get { return from_Address; }
            set { from_Address = value; }
        }

        private string list_Name = "";

        [Newtonsoft.Json.JsonProperty]
        [PropertyConfiguration(PropertyType.TextBox)]
        public string List_Name
        {
            get { return list_Name; }
            set { list_Name = value; }
        }

        public override void Initialise()
        {
            this.ModuleName = "Mailing List Form";
            this.ModuleDescription = "Places an mailing list sign up form on the page";
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            var resp = JFormResponse<DefaultJFormClass>.Current;

            if (resp != null && resp.success)
            {
                this.Controls.Add(new LiteralControl("<span class=\"message\">" + this.success_Message + "</span>"));
                JFormResponse<DefaultJFormClass>.Current = null;
            }
            else
            {
                if (!string.IsNullOrEmpty(this.introduction_Message))
                    this.Controls.AddLiteral("<span class=\"message\">" + this.introduction_Message + "</span>");

                MailingListOptions options = new MailingListOptions();
                options.ToAddress = this.to_Address;
                options.FromAddress = this.from_Address;
                options.Role = this.add_To_Role;
                if (this.list_Name.Length != 0)
                    options.ListName = this.list_Name;
                else
                    options.ListName = this.ModuleId;

                XmlSerializer Serializer = new XmlSerializer(typeof(MailingListOptions));
                StringWriter optionsStream = new StringWriter();
                Serializer.Serialize(optionsStream, options);
                Utils.Encryption.SimpleAES aes = new Encryption.SimpleAES();
                string encyptedOptions = aes.EncryptToString(optionsStream.ToString());

                if (form.IndexOf(",") == -1 && System.IO.File.Exists(Server.MapPath("~/Forms/" + form + ".tpl")))
                {
                    this.Controls.Add(new JForm(form, "/cms/modules/MethodHandler/OpenQuarters.WebQuarters.Modules.MailingList,MailingListModule,FormHandler", new { cmsEnv_options = encyptedOptions })
                    {
                        UseJavaScript = this.use_JavaScript,
                    });
                }
                else
                {
                    this.Controls.Add(new JForm(form, JForm.TemplateType.EmbeddedResource, "/cms/modules/MethodHandler/OpenQuarters.WebQuarters.Modules.MailingList,MailingListModule,FormHandler", new { cmsEnv_options = encyptedOptions })
                    {
                        UseJavaScript = this.use_JavaScript,
                    });
                }
            }
        }

        [Invokable]
        public static JFormResponse<DefaultJFormClass> FormHandler(HttpRequest request)
        {
            var resp = new JFormResponse<DefaultJFormClass>();

            if (request.Form["cmsEnv_options"] != null)
            {
                try
                {
                    Utils.Encryption.SimpleAES aes = new Encryption.SimpleAES();
                    XmlSerializer Serializer = new XmlSerializer(typeof(MailingListOptions));
                    MailingListOptions options = (MailingListOptions)Serializer.Deserialize(new StringReader(aes.DecryptString(request.Form["cmsEnv_options"])));

                    User user = new User();

                    user.UserId = Guid.NewGuid().ToString();
                    user.VerificationCode = Guid.NewGuid().ToString();

                    if (!string.IsNullOrEmpty(request.Form["FirstName"]))
                        user.FirstName = request.Form["FirstName"];

                    if (!string.IsNullOrEmpty(request.Form["Surname"]))
                        user.Surname = request.Form["Surname"];

                    if (string.IsNullOrEmpty(request.Form["FirstName"]) && string.IsNullOrEmpty(request.Form["Surname"]))
                    {
                        if (!string.IsNullOrEmpty(request.Form["Name"]))
                        {
                            string[] name = request.Form["Name"].Split(' ');
                            user.FirstName = name[0];
                            if (name.Length > 1)
                                user.Surname = name[1];
                        }
                    }

                    if (string.IsNullOrEmpty(request.Form["Email"]))
                        resp.errorMessages["Email"].Add("You must enter a valid email address");
                    else
                        user.Email = request.Form["Email"];

                    if (resp.success)
                    {
                        user.Password = Utils.GeneralUtils.MD5Encrypt("mailinglist");

                        //Save WebQuarters user
                        user = user.Save();

                        //Add to user role
                        Core.User.AddToRole(user.UserId, options.Role);

                        //Create mailinglist entry
                        //MailingList listEntry = new MailingList();
                        //listEntry.UserId = user.UserId;
                        //listEntry.DateCreated = DateTime.Now;
                        //listEntry.DateSubscribed = DateTime.Now;
                        //listEntry.Data = request.Form.ToJSON().ToString();
                        //listEntry.ListName = options.ListName;
                        //listEntry = listEntry.Save();

                        // Send copy to email
                        if (options.ToAddress.Length != 0 && options.ToAddress.Length != 0)
                        {
                            StringBuilder sb = new StringBuilder();

                            foreach (string field in request.Form.Keys)
                            {
                                if (field.PadRight(7).Substring(0, 7) != "cmsEnv_")
                                    sb.AppendLine(field + ": " + request.Form[field]);
                            }

                            bool sent = false;
                            string emailClass = Oracle.GetSettings().ProviderSettings["Email"].Value;

                            foreach (Type testClass in GeneralUtils.GetSubclassesOf(typeof(Core.IEmailProvider), true))
                            {
                                if (testClass.FullName == emailClass)
                                {
                                    try
                                    {
                                        ((IEmailProvider)Activator.CreateInstance(GeneralUtils.GetTypeByName(emailClass))).SendEmail(options.ToAddress, options.FromAddress, "", "", string.Format("WebSite - New Mailing List Subscription ({0})", options.ListName), sb.ToString(), false);
                                        sent = true;
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new ApplicationException("The Email Provider (" + emailClass + ") threw an exception.", ex);
                                    }
                                }
                            }

                            if (!sent)
                                throw new ApplicationException("The Email Provider (" + emailClass + ") was not found");

                        }
                    }
                }
                catch
                {

                }
            }
            else
            {
                resp.errorMessages["General"].Add("The data supplied was corrupted, please try again.");
            }

            JFormResponse<DefaultJFormClass>.Current = resp;

            return resp;
        }
    }
}
